﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using EasyHttp.Http;
using Hikvision.Ys.Containers;
using Hikvision.Ys.DeviceApis;
using Hikvision.Ys.LiveApis;
using IiiToolkitMain.Common.Dto;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;


namespace IiiToolkitMain.Common
{

    public class AccessTokenResult
    {
        public Data data { get; set; }
        public string code { get; set; }
        public string msg { get; set; }
    }
    public class Data
    {
        public string accessToken { get; set; }
        public long expireTime { get; set; }
    }

    public class HkAction : IDisposable
    {
        public string _SafeKey = "ABCDEF";
        private static string GetAccessTokenUrl = "https://open.ys7.com/api/lapp/token/get";
        private static string AuthAddr = "https://auth.ys7.com";
        private static string PlatformAddr = "https://open.ys7.com";

        private string _appKey;
        private string _secret;
        private string _userId;
        public HkSDK.MessageHandler msgCallback;

        public string AccessToken
        {
            get
            {
                if (!AccessTokenContainer.CheckRegistered(_appKey))
                {
                    AccessTokenContainer.Register(_appKey, _secret);
                }

                return AccessTokenContainer.GetAccessToken(_appKey);
            }
        }

        private async Task<AccessTokenResult> GetAccessToken(string appKey, string secret)
        {
            HttpClient http = new HttpClient();
            http.Request.Accept = HttpContentTypes.ApplicationJson;
            var response = http.Post(GetAccessTokenUrl, new Dictionary<string, object>()
            {
                {"appKey", appKey},
                {"appSecret", secret},
            }, null);
            AccessTokenResult result = response.StaticBody<AccessTokenResult>();
            return result;
        }




        public HkAction(string appKey, string secret)
        {
            _appKey = appKey;
            _secret = secret;
            this._userId = Guid.NewGuid().ToString("D");
            AccessTokenContainer.Register(_appKey, _secret);
        }

        #region tools
        //MD5加密
        static string MD5Encrypt(string str, int code)
        {
            MD5 md = new MD5CryptoServiceProvider();
            Encoding encoding = Encoding.UTF8;
            byte[] buffer = md.ComputeHash(encoding.GetBytes(str));
            StringBuilder builder = new StringBuilder(code);
            for (int i = 0; i < buffer.Length; i++)
            {
                builder.Append(buffer[i].ToString("x").PadLeft(2, '0'));
            }
            return builder.ToString();
        }

        #endregion

        public bool Start()
        {
            return (HkSDK.OpenSDK_InitLib(AuthAddr, PlatformAddr, _appKey) == 0);
        }

        public bool Close()
        {
            return (HkSDK.OpenSDK_FiniLib() == 0);
        }


        IntPtr _sessionId;
        int _sessionIdLength;
        /// <summary>
        /// 申请会话
        /// </summary>
        /// <returns></returns>
        public IntPtr AllocSession()
        {
            IntPtr userId = Marshal.StringToHGlobalAnsi(_userId);
            bool ret = HkSDK.OpenSDK_AllocSession(msgCallback, userId, ref _sessionId, ref _sessionIdLength, false,
                uint.MaxValue) == 0;
            Marshal.PtrToStringAnsi(_sessionId, _sessionIdLength);
            return _sessionId;
        }


        //结束会话
        public bool CloseSession(IntPtr sid)
        {
            string sid1 = sid.ToString();
            return (HkSDK.OpenSDK_FreeSession(sid1) == 0);
        }

        public CameraListResult GetDeviceList(int pageIndex, int pageSize)
        {
            CameraListResult result = new CameraListResult();

            IntPtr iMessage;
            int iLength;
            int ret = HkSDK.OpenSDK_Data_GetDevList(AccessToken, 0, 50, out iMessage, out iLength);
            //string returnstr = @"{""cameraList"":[{""cameraId"":""5c6cb2bfcf94408fbc664d15d6dd7984"",""cameraName"":""逸风科技 - 办公"",""cameraNo"":1,""defence"":0,""deviceId"":""51ed24b5d4fe4de0bf85b3b419514ea0585171107"",""deviceName"":""逸风科技 - 办公"",""deviceSerial"":""585171107"",""isEncrypt"":0,""isShared"":""1"",""picUrl"":""https://i.ys7.com/assets/imgs/public/homeDevice.jpeg"",""status"":1,""videoLevel"":2},{""cameraId"":""b46e06d87c264a0e92489a224ab0b504"",""cameraName"":""C2C(651770117)"",""cameraNo"":1,""defence"":0,""deviceId"":""51ed24b5d4fe4de0bf85b3b419514ea0651770117"",""deviceName"":""C2C(651770117)"",""deviceSerial"":""651770117"",""isEncrypt"":0,""isShared"":""1"",""picUrl"":""https://i.ys7.com/assets/imgs/public/homeDevice.jpeg"",""status"":1,""videoLevel"":2}],""count"":2,""resultCode"":""200""}";
            string returnstr = Marshal.PtrToStringAnsi(iMessage);
            if (ret == 0)
            {
                result = JsonConvert.DeserializeObject<CameraListResult>(returnstr);
            }
            return result;
        }

        public CameraInfoResult GetDeviceInfo(string deviceSerial)
        {
            CameraInfoResult result = null;
            IntPtr iMessage;
            int iLength;
            int ret = HkSDK.OpenSDK_Data_GetDeviceInfo(AccessToken, deviceSerial, out iMessage, out iLength);
            string returnstr = Marshal.PtrToStringAnsi(iMessage);
            if (ret == 0)
            {
                JObject res = JObject.Parse(returnstr);
                result = JsonConvert.DeserializeObject<CameraInfoResult>(res["result"].ToString());
            }
            return result;
        }
        public CameraDetailResult GetDeviceDetail(string deviceSerial, int channelNo, bool getNew = false)
        {
            CameraDetailResult result = null;
            IntPtr iMessage;
            int iLength;
            int ret = HkSDK.OpenSDK_Data_GetDevDetailInfo(deviceSerial, channelNo, getNew, out iMessage, out iLength);
            string returnstr = Marshal.PtrToStringAnsi(iMessage);
            if (ret == 0)
            {
                result = JsonConvert.DeserializeObject<CameraDetailResult>(returnstr);
            }
            return result;
        }
        /// <summary>
        /// 播放视频
        /// </summary>
        /// <param name="playWnd"></param>
        /// <param name="sessionId"></param>
        /// <param name="cameraId"></param>
        /// <param name="level">清晰度，0流畅，1标清，2高清</param>
        /// <returns></returns>
        public bool Play(IntPtr playWnd, IntPtr sessionId, string cameraId, int level)
        {
            return (HkSDK.OpenSDK_StartRealPlay(sessionId, playWnd, cameraId, AccessToken, level, _SafeKey, this._appKey, 0) == 0);
        }

        public bool Stop(IntPtr sessionId)
        {
            HkSDK.OpenSDK_FreeSession(sessionId.ToString());
            if (HkSDK.OpenSDK_StopRealPlay(sessionId, 0) == 0)
                return HkSDK.OpenSDK_StopRealPlay(sessionId, 0) == 0;
            return false;
        }


        public bool PtzCtrl_Start(IntPtr sessionId, string deviceSerial, int channelNo, HkSDK.PTZCommand cmd, int speed)
        {
            try
            {
                var ret = DevicePtzApi.StartOperate(this._appKey, deviceSerial, channelNo, (int) cmd, speed);
                return ret.Success;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            return false;
        }

        public bool PtzCtrl_Stop(IntPtr sessionId, string deviceSerial, int channelNo)
        {
            try
            {
                var ret = DevicePtzApi.StopOperate(this._appKey, deviceSerial, channelNo);
                return ret.Success;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            return false;
        }

        public bool StartVoiceTalk(IntPtr sessionId, string deviceSerial, int channelNo)
        {
            try
            {
                var ret = HkSDK.OpenSDK_StartVoiceTalk(sessionId, deviceSerial, channelNo);
                return ret == 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            return false;
        }

        public bool StopVoiceTalk(IntPtr sessionId)
        {
            var ret = HkSDK.OpenSDK_StopVoiceTalk(sessionId);
            return ret == 0;
        }
        public bool CapturePicture(IntPtr sessionId,string fileName)
        {
            var ret = HkSDK.OpenSDK_CapturePicture(sessionId,fileName);
            return ret == 0;
        }
        public void Dispose()
        {
            this.Close();
        }

    }
}